package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;

import javax.sql.DataSource;

/**
 *  和Spring连接数据库相关的配置类
 *
 *  @Configuration //必须识别它是一个配置类，才会对注解进行扫描
 * 用于定义配置类，可替换xml配置文件，被注解的类内部包含有一个或多个被@Bean注解的方法，
 * 这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描，并用于构建bean定义，初始化Spring容器
 * 同时，也可以配置扫描，将注解修饰的类扫描进容器。
 *
 *  1.    PropertySource
 *        作用：用于指定properties文件的位置
 *        属性：
 *           value：指定文件的名称和路径
 *                关键字：classpath，表示类路径下
 *  其它：
 *      配置可以是
 *          1.纯XML
 *          2.纯Java配置
 *          3.混合配置（Java配置+XML配置。混用的话，可以在Java配置中引入XML配置）
 *              @Configuration
 *              @ImportResource("classpath:applicationContext.xml")
 *              public class JavaConfig {
 *              }
 *              在加载这个Java配置类的时候，有@ImportResource注解，会去加载这个xml配置，生成Bean，放入容器
 */

@Configuration //必须识别它是一个配置类，才会对注解进行扫描
@PropertySource("classpath:jdbcConfig.properties")
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver ;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /**
     *  用于创建一个QueryRunner对象
     * - @Bean:这个注解只用写在方法上，表明使用此方法创建一个对象，并且放在Spring容器中
     *          属性：name，用于指定bean的id，不写就默认当前的方法名
     *         细节：
     *              当我们使用注解配置方法的时候，如果方法有参数，Spring框架回去容器查找有没有可用的bean，
     *         查找的方式和@AutoWired注解是一样的，没有，唯一一个，多个
     *         有唯一一个的时候：
     *                   createQueryRunner(DataSource dataSource)
     *                  其实隐藏了@AutoWired注解
     *         当有多个的时候：
     *                      1. 可以将变量名称和bean的id设为一样的
     *                      2. 使用@Qualifier注解进行限定
     *
     * - @Qualifier：在按照类中注入的基础上再按照名称注入。它在给类成员注入时候，不能单独使用，给方法参数注入时可以单独使用
     *              value：用于指定注入bean的id。
     *
     */
    @Bean(name="runnerAnnotation")
    @Scope("prototype")
    public QueryRunner createQueryRunner(@Qualifier("ds") DataSource dataSource){
        //在xml总bean标签（我猜测相当于自动走默认构造方法，帮我们创建对象，存入到Spring容器中）
        return new QueryRunner(dataSource);
    }

    /**
     *  创建数据源对象
     *  如果只有一个，可以不用@Qualifier 直接能够自动注入成功；
     *  当有多个的时候，1.可以通过变量名字是id；
     *                  2. 可以通过@Qualifier（限定）注入|引用AutoWired
     */
    @Bean(name = "ds")
    public DataSource createDataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        try {
            dataSource.setDriverClass(driver);
            dataSource.setJdbcUrl(url);
            dataSource.setUser(username);
            dataSource.setPassword(password);
            return dataSource;
        } catch (Exception e) {
           throw  new RuntimeException(e);
        }
    }






}
